package open.intellijboy.framework.core.util;

import lombok.extern.slf4j.Slf4j;
import open.intellijboy.framework.core.constant.CommonConstants;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.regex.Pattern;

/**
 * 密码工具类
 *
 * @author System
 * @version 1.0.0
 * @since 2024-01-01
 */
@Slf4j
public final class PasswordUtil {

    private static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
    private static final Pattern PASSWORD_PATTERN = Pattern.compile(CommonConstants.PASSWORD_PATTERN);

    private PasswordUtil() {
        throw new UnsupportedOperationException("Utility class");
    }

    /**
     * 加密密码
     *
     * @param rawPassword 原始密码
     * @return 加密后的密码
     */
    public static String encode(String rawPassword) {
        if (rawPassword == null || rawPassword.trim().isEmpty()) {
            throw new IllegalArgumentException("密码不能为空");
        }
        return PASSWORD_ENCODER.encode(rawPassword);
    }

    /**
     * 验证密码
     *
     * @param rawPassword     原始密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean matches(String rawPassword, String encodedPassword) {
        if (rawPassword == null || encodedPassword == null) {
            return false;
        }
        return PASSWORD_ENCODER.matches(rawPassword, encodedPassword);
    }

    /**
     * 验证密码强度
     *
     * @param password 密码
     * @return 验证结果
     */
    public static PasswordValidationResult validatePassword(String password) {
        if (password == null) {
            return new PasswordValidationResult(false, "密码不能为空");
        }

        if (password.length() < CommonConstants.PASSWORD_MIN_LENGTH) {
            return new PasswordValidationResult(false,
                String.format("密码长度不能少于%d位", CommonConstants.PASSWORD_MIN_LENGTH));
        }

        if (password.length() > CommonConstants.PASSWORD_MAX_LENGTH) {
            return new PasswordValidationResult(false,
                String.format("密码长度不能超过%d位", CommonConstants.PASSWORD_MAX_LENGTH));
        }

        if (!PASSWORD_PATTERN.matcher(password).matches()) {
            return new PasswordValidationResult(false,
                "密码必须包含字母和数字，长度6-20位");
        }

        return new PasswordValidationResult(true, "密码格式正确");
    }

    /**
     * 生成随机密码
     *
     * @param length 密码长度
     * @return 随机密码
     */
    public static String generateRandomPassword(int length) {
        if (length < 6 || length > 20) {
            length = 8; // 默认长度
        }

        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder password = new StringBuilder();

        // 确保至少包含一个字母和一个数字
        password.append(chars.charAt((int) (Math.random() * 26))); // 大写字母
        password.append(chars.charAt((int) (Math.random() * 26) + 26)); // 小写字母
        password.append(chars.charAt((int) (Math.random() * 10) + 52)); // 数字

        // 填充剩余长度
        for (int i = 3; i < length; i++) {
            password.append(chars.charAt((int) (Math.random() * chars.length())));
        }

        // 打乱顺序
        return shuffleString(password.toString());
    }

    /**
     * 生成默认密码
     *
     * @return 默认密码
     */
    public static String generateDefaultPassword() {
        return CommonConstants.DEFAULT_PASSWORD;
    }

    /**
     * 检查密码是否为默认密码
     *
     * @param password 密码
     * @return 是否为默认密码
     */
    public static boolean isDefaultPassword(String password) {
        return CommonConstants.DEFAULT_PASSWORD.equals(password);
    }

    /**
     * 打乱字符串顺序
     *
     * @param str 原字符串
     * @return 打乱后的字符串
     */
    private static String shuffleString(String str) {
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            int j = (int) (Math.random() * chars.length);
            char temp = chars[i];
            chars[i] = chars[j];
            chars[j] = temp;
        }
        return new String(chars);
    }

    /**
     * 密码验证结果
     */
    public static class PasswordValidationResult {
        private final boolean valid;
        private final String message;

        public PasswordValidationResult(boolean valid, String message) {
            this.valid = valid;
            this.message = message;
        }

        public boolean isValid() {
            return valid;
        }

        public String getMessage() {
            return message;
        }
    }
}